#include "mex.h"
#include "cc.h"


int init_cuda();
void run_pdist(float *output, float *input, unsigned int size_x, unsigned int size_y);

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	double *inMatrix;
	unsigned int size_x;
	unsigned int size_y;
	double *outMatrix;
	int deviceCount;
	int dev;
	float *in, *out;
	int output_length;

	if (nrhs != 1) {
		mexErrMsgTxt("One input required.");
	}

	if (nlhs > 1) {
		mexErrMsgTxt("Cannot have more than one output.");
	}

	if (mxGetM(prhs[0]) == 1 && mxGetN(prhs[0]) == 1
		|| mxGetM(prhs[0]) == 1) {
		mexErrMsgTxt("Input must be a matrix. Must have more than one row.");
	}

	if (init_cuda() != 0) {
		mexErrMsgTxt("Could not initialize CUDA. Is a CUDA enabled device present?");
	}

	inMatrix = mxGetPr(prhs[0]);
	size_x = mxGetN(prhs[0]);
	size_y = mxGetM(prhs[0]);

	output_length = (size_y * (size_y-1)) / 2;

	out = mxMalloc(sizeof(float)*size_y*size_y);
	if (!out)
		mexErrMsgTxt("Could not alloc out.");
	in = mxMalloc(sizeof(float)*size_x*size_y);
	if (!in) {
		mxFree(out);
		mexErrMsgTxt("Could not alloc in.");
	}
	plhs[0] = mxCreateDoubleMatrix(1, output_length, mxREAL);
	outMatrix = mxGetPr(plhs[0]);
	if (!outMatrix) {
		mxFree(out);
		mxFree(in);
		mexErrMsgTxt("Could not alloc outMatrix.");
	}

	double2float(in, inMatrix, size_x, size_y, 0);

	run_pdist(out, in, size_x, size_y);

	float2double_lower_triangle(outMatrix, out, size_y, size_y);

	mxFree(in);
	mxFree(out);
}
